﻿namespace PCBase.UIControls
{
    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Drawing;
    using System.Linq;
    using System.Reflection;
    using System.Runtime.CompilerServices;
    using System.Text.RegularExpressions;
    using System.Threading;
    using System.Windows.Forms;

    [Description("带输入验证功能的文本框。.Net 3.5 以上版本使用")]
    public class RegexTextBox : TextBox
    {
        private ToolTip _tooltip;
        private bool allowEmpty;
        private Color backColor;
        private Button button;
        private Button button2;
        private IContainer components;
        private string emptyMessage;
        private ErrorShowMethod errMethod;
        private string errorMessage;
        private ErrorProvider errpro;
        private static Hashtable ht = new Hashtable();
        private Color invalidBackColor;
        private Label label;
        private string messageTitle;
        private string regexExpression;
        private bool removeSpace;
        private static IList<RegexTextBox> txtList = new List<RegexTextBox>();
        private ValidateMethod validate;

        private static frmKeyBoard frmInput = null;


        [Description("自定义验证事件"), Category("验证")]
        public event CustomerValidatedHandler CustomerValidated;

        public RegexTextBox()
        {
            this.errpro = new ErrorProvider();
            this.invalidBackColor = Color.White;
            this.backColor = Color.White;
            this.allowEmpty = true;
            this.messageTitle = "提示";
            this.InitializeComponent();
            this.errpro.BlinkStyle = ErrorBlinkStyle.NeverBlink;
            base.TextChanged += new EventHandler(this.RegexTextBox_TextChanged);
            base.MouseDoubleClick += RegexTextBox_MouseDoubleClick;
        }
        public RegexTextBox(IContainer container)
        {
            this.errpro = new ErrorProvider();
            this.invalidBackColor = Color.White;
            this.backColor = Color.White;
            this.allowEmpty = true;
            this.messageTitle = "提示";
            container.Add(this);
            this.InitializeComponent();
            this.errpro.BlinkStyle = ErrorBlinkStyle.NeverBlink;
            base.TextChanged += new EventHandler(this.RegexTextBox_TextChanged);
            base.MouseDoubleClick += RegexTextBox_MouseDoubleClick;
        }

        void RegexTextBox_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            if (RegexTextBox.frmInput == null)
            {
                RegexTextBox.frmInput = new frmKeyBoard();
            }
            Form f = this.FindForm();
            frmInput.ShowKeyBoard(f, "光源亮度", Text);

            this.Text = frmInput.DataString;

            Focus();
            Select(TextLength, 0);

        }

        private void button_Click(object sender, EventArgs e)
        {
            foreach (RegexTextBox box in from c in (from c in txtList
                                                    where c.ButtonToValidate == (sender as Button)
                                                    select c).Distinct<RegexTextBox>()
                                         orderby c.TabIndex
                                         select c)
            {
                if (box.Enabled)
                {
                    if (box.label != null)
                    {
                        box.label.Text = "";
                    }
                    if (!box.AllowEmpty && ((box.RemoveSpace && (box.Text.Trim() == "")) || (box.Text == "")))
                    {
                        box.ShowErrorMessage(box.EmptyMessage);
                        box.SelectAll();
                        box.Focus();
                        return;
                    }
                    if ((!box.RemoveSpace || (box.Text.Trim() != "")) && (box.Text != ""))
                    {
                        if ((((box.validate == ValidateMethod.Default) && (box.RegexExpression != null)) && (box.RegexExpression.Trim() != "")) && !Regex.IsMatch(box.RemoveSpace ? box.Text.Trim() : box.Text, box.RegexExpression))
                        {
                            box.ShowErrorMessage(box.ErrorMessage);
                            box.SelectAll();
                            box.Focus();
                            return;
                        }
                        if (box.CustomerValidated != null)
                        {
                            CustomerEventArgs args = new CustomerEventArgs
                            {
                                Value = box.Text,
                                Validated = true
                            };
                            box.CustomerValidated(box, args);
                            if (!args.Validated)
                            {
                                box.ShowErrorMessage(args.ErrorMessage);
                                box.SelectAll();
                                box.Focus();
                                return;
                            }
                        }
                        double result = 0.0;
                        if (box.RangeCheck && double.TryParse(box.Text, out result))
                        {
                            if (box.RangeMinValue > box.RangeMaxValue)
                            {
                                box.ShowErrorMessage(string.Format("范围最大值不能小于最小值,请更改范围最大值&最小值", box.RangeMinValue, box.RangeMaxValue));
                                box.Focus();
                                return;
                            }
                            if (((result - box.RangeMaxValue) > 0.0) || ((result - box.RangeMinValue) < 0.0))
                            {
                                box.ShowErrorMessage(string.Format("输入值超范围[{0} - {1}]", box.RangeMinValue, box.RangeMaxValue));
                                box.SelectAll();
                                box.Focus();
                                return;
                            }
                        }
                    }
                }
            }
            foreach (DictionaryEntry entry in ht)
            {
                if (entry.Key == (sender as Button))
                {
                    EventHandler handler = entry.Value as EventHandler;
                    if (handler != null)
                    {
                        handler(sender, e);
                    }
                    break;
                }
            }
        }

        protected override void Dispose(bool disposing)
        {
            txtList.Remove(this);
            if (this.button != null)
            {
                ht.Remove(this.button);
            }
            if (this._tooltip != null)
            {
                this._tooltip.Dispose();
            }
            if (disposing && (this.components != null))
            {
                this.components.Dispose();
            }
            base.Dispose(disposing);
        }

        private void InitializeComponent()
        {
            this.components = new Container();
        }

        protected override void OnCreateControl()
        {
            base.OnCreateControl();
            if (!base.DesignMode)
            {
                this.ReButtonEvent();
            }
        }

        private void ReButtonEvent()
        {
            if ((this.button != null) && ((from c in ht.Keys.Cast<Button>()
                                           where c == this.button
                                           select c).Count<Button>() == 0))
            {
                PropertyInfo property = this.button.GetType().GetProperty("Events", BindingFlags.NonPublic | BindingFlags.Instance);
                if (property != null)
                {
                    EventHandlerList list = (EventHandlerList)property.GetValue(this.button, null);
                    if ((list != null) && (list != null))
                    {
                        FieldInfo field = typeof(Control).GetField("EventClick", BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.IgnoreCase);
                        if (field != null)
                        {
                            EventHandler handler = list[field.GetValue(this.button)] as EventHandler;
                            if (handler != null)
                            {
                                this.button.Click -= handler;
                            }
                            this.button.Click += new EventHandler(this.button_Click);
                            ht.Add(this.button, handler);
                        }
                    }
                }
            }
        }

        private void RegexTextBox_TextChanged(object sender, EventArgs e)
        {
            if (this._tooltip != null)
            {
                this._tooltip.Dispose();
            }
            if (this.label != null)
            {
                this.label.Text = "";
            }
            this.errpro.Clear();
            base.BackColor = this.backColor;
        }

        private void SetBackColor(Color color)
        {
            base.BackColor = color;
        }

        private void ShowErrorMessage(string err)
        {
            this.SetBackColor(this.invalidBackColor);
            switch (this.ShowMethod)
            {
                case ErrorShowMethod.MessageBox:
                    MessageBox.Show(err, this.messageTitle, MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                    return;

                case ErrorShowMethod.Label:
                    if (this.label != null)
                    {
                        this.label.Text = err;
                        this.label.Visible = true;
                        return;
                    }
                    return;

                case ErrorShowMethod.ToolTip:
                    if (this._tooltip != null)
                    {
                        this._tooltip.Dispose();
                    }
                    this._tooltip = new ToolTip();
                    this._tooltip.ToolTipIcon = ToolTipIcon.Warning;
                    this._tooltip.IsBalloon = true;
                    this._tooltip.ToolTipTitle = this.messageTitle;
                    this._tooltip.AutoPopDelay = 0x1388;
                    if (err != null)
                    {
                        int length = err.Split(new string[] { "\r\n", "\r", "\n" }, StringSplitOptions.RemoveEmptyEntries).Length;
                        this._tooltip.Show(err, this, new Point(10, (-47 - (length * 0x12)) + ((base.Height - 0x15) / 2)));
                    }
                    else
                    {
                        this._tooltip.Show("", this, new Point(10, -65 + ((base.Height - 0x15) / 2)));
                    }
                    return;

                case ErrorShowMethod.Icon:
                    this.errpro.SetError(this, err);
                    return;
            }
        }

        [Category("验证"), Description("获取或设置是否允许空值"), DefaultValue(true)]
        public bool AllowEmpty
        {
            get
            {
                return this.allowEmpty;
            }
            set
            {
                this.allowEmpty = value;
            }
        }

        [DefaultValue(typeof(Color), "White")]
        public override Color BackColor
        {
            get
            {
                return this.backColor;
            }
            set
            {
                this.backColor = value;
                base.BackColor = value;
            }
        }

        [Description("获取或设置与之验证相关的按钮"), Category("验证"), DefaultValue((string)null)]
        public Button ButtonToValidate
        {
            get
            {
                return this.button;
            }
            set
            {
                Func<RegexTextBox, bool> func = null;
                Func<Button, bool> func2 = null;
                if (!base.DesignMode)
                {
                    if (value != null)
                    {
                        if (!txtList.Contains(this))
                        {
                            txtList.Add(this);
                        }
                    }
                    else
                    {
                        if (txtList.Contains(this))
                        {
                            txtList.Remove(this);
                        }
                        if (this.button != null)
                        {
                            if (func == null)
                            {
                                func = c => c.ButtonToValidate == this.button;
                            }
                            if (Enumerable.Where<RegexTextBox>(txtList, func).Count<RegexTextBox>() == 0)
                            {
                                if (func2 == null)
                                {
                                    func2 = c => c == this.button;
                                }
                                if (Enumerable.Where<Button>(ht.Keys.Cast<Button>(), func2).Count<Button>() > 0)
                                {
                                    this.button.Click -= new EventHandler(this.button_Click);
                                    foreach (DictionaryEntry entry in ht)
                                    {
                                        if (entry.Key == this.button)
                                        {
                                            EventHandler handler = entry.Value as EventHandler;
                                            this.button.Click += handler;
                                            break;
                                        }
                                    }
                                    ht.Remove(this.button);
                                }
                            }
                        }
                    }
                }
                this.button = value;
            }
        }

        [Category("验证"), Description("获取或设置与之验证相关的按钮"), DefaultValue((string)null)]
        public Button ButtonToValidate2
        {
            get
            {
                return this.button2;
            }
            set
            {
                this.button2 = value;
            }
        }

        [Description("获取或设置当控件的值为空的时候显示的信息"), DefaultValue(""), Category("验证")]
        public string EmptyMessage
        {
            get
            {
                return this.emptyMessage;
            }
            set
            {
                this.emptyMessage = value;
            }
        }

        [Category("验证"), Description("用于指示错误的图标")]
        public Icon ErrorIcon
        {
            get
            {
                return this.errpro.Icon;
            }
            set
            {
                this.errpro.Icon = value;
            }
        }

        [Description("获取或设置当不满足正则表达式结果的时候显示的错误信息"), DefaultValue(""), Category("验证")]
        public string ErrorMessage
        {
            get
            {
                return this.errorMessage;
            }
            set
            {
                this.errorMessage = value;
            }
        }

        [Description("获取或设置未通过验证时文本框的背景色"), DefaultValue(typeof(Color), "White"), Category("验证")]
        public Color InvalidBackColor
        {
            get
            {
                return this.invalidBackColor;
            }
            set
            {
                this.invalidBackColor = value;
            }
        }

        [DefaultValue((string)null), Category("验证"), Description("获取或设置与之相关联的标签")]
        public Label MessageLabel
        {
            get
            {
                return this.label;
            }
            set
            {
                this.label = value;
                if (value != null)
                {
                    this.errMethod = ErrorShowMethod.Label;
                    if (!base.DesignMode)
                    {
                        this.label.Text = "";
                    }
                }
                else
                {
                    this.errMethod = ErrorShowMethod.MessageBox;
                }
            }
        }

        [Category("验证"), DefaultValue("提示"), Description("获取或设置显示消息框的标题")]
        public string MessageTitle
        {
            get
            {
                return this.messageTitle;
            }
            set
            {
                this.messageTitle = value;
                this._tooltip.ToolTipTitle = value;
            }
        }

        [DefaultValue(false), Category("验证"), Description("获取或设置是否进行数值范围验证")]
        public bool RangeCheck { get; set; }

        [Category("验证"), Description("数值范围验证之最大值"), DefaultValue(100)]
        public double RangeMaxValue { get; set; }

        [Category("验证"), DefaultValue(1), Description("数值范围验证之最小值")]
        public double RangeMinValue { get; set; }

        [DefaultValue(""), Description("获取或设置用于验证控件值的正则表达式"), Category("验证")]
        public string RegexExpression
        {
            get
            {
                return this.regexExpression;
            }
            set
            {
                this.regexExpression = value;
            }
        }

        [DefaultValue(false), Category("验证"), Description("获取或设置验证的时候是否除去头尾空格")]
        public bool RemoveSpace
        {
            get
            {
                return this.removeSpace;
            }
            set
            {
                this.removeSpace = value;
            }
        }

        [DefaultValue(0), Description("获取或设置提示信息显示的方式"), Category("验证")]
        public ErrorShowMethod ShowMethod
        {
            get
            {
                return this.errMethod;
            }
            set
            {
                if ((value == ErrorShowMethod.Label) && (this.label == null))
                {
                    throw new Exception("必须先设置与之关联的Label控件");
                }
                this.errMethod = value;
            }
        }

        [Description("获取或设置验证方式"), DefaultValue(0), Category("验证")]
        public ValidateMethod Validate
        {
            get
            {
                return this.validate;
            }
            set
            {
                this.validate = value;
            }
        }
    }
}

